﻿using Signit.Sdk.Extentions;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Web;
using Viyi.Util.Linq;

namespace Signit.Sdk.Http
{
    partial class HttpClientSync
    {
        private const string USER_AGENT = "Signit HTTP";
        private const string DEFAULT_ENCODING = "UTF-8";

        private static Response ConvertResponse(HttpResponseMessage response, bool needContentOnError = false)
        {
            var result = new Response()
            {
                IsSuccessStatusCode = response.IsSuccessStatusCode,
                Code = response.StatusCode
            };

            if (needContentOnError || response.IsSuccessStatusCode)
            {
                result.Content = response.Content.ReadAsStringAsync().WaitResult();
            }

            Debug.WriteLine($"[RESPONSE] {result.Content}");
            return result;
        }

        private NameValueCollection queryParams = new NameValueCollection();
        private Authentication authentication;

        public Response Get(string url)
        {
            url = ConcatQueryString(url);

            Debug.WriteLine($"[GET] {url}");
            HttpClient client = new HttpClient();
            var response = client.GetAsync(url).WaitResult();
            return ConvertResponse(response);
        }

        public Response Post(string url, object payload, NameValueCollection headers = null)
        {
            url = ConcatQueryString(url);
            url = ConcatQueryParam(url, "access_token", authentication.AccessToken);

            var content = new JsonContent(payload);

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            client.DefaultRequestHeaders.Add("Accept-Encoding", DEFAULT_ENCODING);
            client.DefaultRequestHeaders.Add("User-Agent", USER_AGENT);

            headers?.AllKeys.ForEach(key =>
            {
                client.DefaultRequestHeaders.Add(key, headers[key]);
            });

            Debug.WriteLine($"[POST] {url}");
            var response = client.PostAsync(url, content).WaitResult();
            return ConvertResponse(response, true);
        }


        private static string ConcatQueryParam(string url, string key, string value)
        {
            var pair = $"{key}={HttpUtility.UrlEncode(value)}";
            return $"{url}{(url.Contains("?") ? "&" : "?")}{pair}";
        }

        private string ConcatQueryString(string url)
        {
            var pairs = queryParams.AllKeys
                .SelectMany(key =>
                {
                    return queryParams.GetValues(key)
                        .Select(v => $"{key}={HttpUtility.UrlEncode(v)}");
                });
            var queryString = string.Join("&", pairs);

            if (!string.IsNullOrEmpty(queryString))
            {
                url = $"{url}{(url.Contains("?") ? "&" : "?")}{queryString}";
            }

            return url;
        }

        public HttpClientSync AddQueryParam(string name, string value)
        {
            queryParams.Add(name, value);
            return this;
        }

        public HttpClientSync WithAuthentication(Authentication auth)
        {
            authentication = auth;
            return this;
        }
    }
}
